package net.xlsa.common.licence;

import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

import org.apache.commons.tfs.DefaultLicence;
import org.apache.commons.tfs.DesUtils;
import org.apache.commons.tfs.SignProvider;
import org.apache.commons.tfs.VersionType;

public class LicenceCreator extends DefaultLicence {

	private static final byte[] PUBLIC_KEY = ("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjICVNTUNarL+eHZ1IDCAWAX/oEfMktdLSp5XP"
			+ "+REvVWMO8ZTnuM4Pddh819D97EtPIrivIYNsxCTJPQt7+ldfaJnEtImRq1iXLlPRuFqAiU2dVkS2"
			+ "uFvcCEnrffBav/RDazod0bC4Oa77nSdRJlxCcyBUKeTsV65Qls3clbe/XQIDAQAB")
			.getBytes();

	private static final byte[] PRIVATE_KEY = ("MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAKMgJU1NQ1qsv54dnUgMIBYBf+gR"
			+ "8yS10tKnlc/5ES9VYw7xlOe4zg912HzX0P3sS08iuK8hg2zEJMk9C3v6V19omcS0iZGrWJcuU9G4"
			+ "WoCJTZ1WRLa4W9wISet98Fq/9ENrOh3RsLg5rvudJ1EmXEJzIFQp5OxXrlCWzdyVt79dAgMBAAEC"
			+ "gYEAoAgbUDjqSPyMh+v5rwLmP3B9MQjbBjqydyMdoAhyyYL1SWXLdYEh9pzgI6n+R/4W663ejUFN"
			+ "k9jhVeNjbt9r8oYtQ9dCu2wRzNgQyTj9WCop9TYFkO86BqOdCjO6zCJmiyJMYsY5wkm3PTs+miWT"
			+ "6ufKTDGaLskv8+9kzNk9dikCQQDYL0/cOx6gX9+lla8l+oCiUBZiqypJYHOHwEgGZmQ0oR4uWQdq"
			+ "/i8LouXVOR6SRgPLzD0BKVoFTcRSTFe6Ja73AkEAwSsx6QsTfpyHXS0j1LVAWiouNxxN2IqTOCS8"
			+ "HFR1GBdn31Gnc8+fykR4Y9rXRvP11lkBA2QHNhqj/DoeNYYrSwJBAMtNswypjGPFxc0yt0RAEDiU"
			+ "mHix/1KCIiPH7/QU1qen3Xo4v4EfCZ8n0nxy+w0USv2dVMGC4eWa/MVohhfI2IECQQCM7jy9r40L"
			+ "hJvlyPcpSwumPLv3DTlmUMPT5EkxyhSb/QeVkHdBMSt9YLMM9y6032xudAUfOi1gtdMKRESh/D89"
			+ "AkEAst2aQ5WdQCOSlqVnvkq8/U5jVQKtAI+k/u8Gaff7PiIL2ibXJkYJE25YV3HsG+NpN01ZAQvb"
			+ "ccCQUMXozNLjxw==").getBytes();

	private static final String DES_KEY = "rs2UYchhSYU=";

	private static final char SEPERATOR = '~';

	private static final SimpleDateFormat DATE_FOMAT = new SimpleDateFormat(
			"yyyyMMdd");

	private static final String KEY_LICENCE = "Licence";

	private static final String KEY_KEY = "Key";

	public static final String EMPTY = "";

	private static final String LICENCE_PATH = "C:\\Users\\LiangBin\\Desktop\\licence.properties";

	/** DES加密后的串 */
	private String key;

	/** 签名后的串 */
	private String licence;

	public LicenceCreator() {
		super();
		setSign(new Date());
	}

	/**
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		LicenceCreator creator = new LicenceCreator();
		creator.setName("勘察管理系统"); // 产品名称
		creator.setCode("XLSA-CMS"); // 产品编码
		creator.setVersion("0.8"); // 版本号
		creator.setVersionType(VersionType.Custom); // 版本类型
		creator.setCopyright("成都远策数码有限公司"); // 版权信息
		creator.setUnit("四川通信科研规划设计有限责任公司"); // 被许可单位
		creator.setExpiry(toDate("20130531")); // 到期日期，空为无限制
		creator.setUserLimit(0); // 许可的用户数，0为无限制
		creator.setBoard(EMPTY); // 被许可的主板序列号，空为无限制
		creator.setCpus(EMPTY); // 被许可的CPU序列号，空为无限制，多个以逗号分隔
		creator.setDisks(EMPTY); // 被许可的硬盘序列号，空为无限，多个以逗号分隔
		creator.setMacs(EMPTY); // 被许可的MAC地址，空为无限制，多个以逗号分隔

//		creator.key = DesUtils.encrypt(creator.toString(), DES_KEY);
//		System.out.println("source=" + creator.key);
//
//		byte[] signature = Signaturer.sign(PRIVATE_KEY, creator.key);
//		creator.licence = new String(signature);
//		System.out.println("signature=" + creator.licence);
//
//		System.out.println("verify="
//				+ SignProvider.verify(PUBLIC_KEY, creator.key, signature));

		creator.generate();
		creator.store();
	}

	public boolean generate() {
		try {
			return doGenerate();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return false;
	}

	private boolean doGenerate() throws Exception {
		key = DesUtils.encrypt(toString(), DES_KEY);
		System.out.println("source=" + key);

		byte[] signature = Signaturer.sign(PRIVATE_KEY, key);
		licence = new String(signature);
		System.out.println("signature=" + licence);

		boolean verify = SignProvider.verify(PUBLIC_KEY, key, signature);
		System.out.println("verify=" + verify);

		return verify;
	}

	@Override
	@Deprecated
	public boolean validate() {
		return true;
	}

	/**
	 * 0名称~1编码~2版本号~3版本类型~4版权~5许可日期~6许可单位~7到期日期~8用户数~9主板~10CPU~11硬盘~12MAC
	 */
	@Override
	public String toString() {
		Date sign = getSign();
		if (sign == null) {
			throw new NullPointerException("Property sign can't be null.");
		}

		Date expiry = getExpiry();
		if (expiry != null && expiry.before(sign)) {
			throw new IllegalArgumentException(
					"Property expiry can't be before now.");
		}

		StringBuilder sb = new StringBuilder();
		sb.append(getName() == null ? EMPTY : getName()).append(SEPERATOR);
		sb.append(getCode() == null ? EMPTY : getCode()).append(SEPERATOR);
		sb.append(getVersion() == null ? EMPTY : getVersion())
				.append(SEPERATOR);
		sb.append(
				getVersionType() == null ? VersionType.Unknown.name()
						: getVersionType().name()).append(SEPERATOR);
		sb.append(getCopyright() == null ? EMPTY : getCopyright()).append(SEPERATOR);
		sb.append(toString(sign)).append(SEPERATOR);
		sb.append(getUnit() == null ? EMPTY : getUnit()).append(SEPERATOR);
		sb.append(toString(expiry)).append(SEPERATOR);
		sb.append(getUserLimit()).append(SEPERATOR);
		sb.append(getBoard() == null ? EMPTY : getBoard()).append(SEPERATOR);
		sb.append(getCpus() == null ? EMPTY : getCpus()).append(SEPERATOR);
		sb.append(getDisks() == null ? EMPTY : getDisks()).append(SEPERATOR);
		sb.append(getMacs() == null ? EMPTY : getMacs());

		return sb.toString();
	}

	private String toString(Date date) {
		if (date == null) {
			return "";
		}
		return DATE_FOMAT.format(date);
	}

	public static Date toDate(String str) throws Exception {
		if (str == null || str.length() == 0) {
			return null;
		}
		return DATE_FOMAT.parse(str);
	}

	public void store() throws Exception {
		store(LICENCE_PATH);
	}
	
	public void store(String filePath) throws Exception {
		Properties properties = new Properties();
		properties.put("Company", getUnit() == null ? EMPTY : getUnit());
		properties.put("Validity", toString(getExpiry()));
		properties.put("IpAddress", getMacs() == null ? EMPTY : getMacs());
		properties.put("UserCount", String.valueOf(getUserLimit()));
		properties.put(KEY_KEY, key);
		properties.put(KEY_LICENCE, licence);
		FileOutputStream os = new FileOutputStream(filePath);
		properties.store(os, null);
		os.close();
	}

}
